package com.jack.userservice.controller;

import com.jack.userservice.openfeign.OrderServiceFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {

    /*
        (1)访问/user/test
        (2)sentinel-core/client: user-service    收集当前接口信息  把整个接口信息写到sentinel-dashboard
        (3)在user-service所在机器上要开一个端口8179，以便sentinel-dashboard能够把对应配置规则传给自己
        (4)在sentinel-server中配置对应的规则，比如流控
        (5)生效的过程：流控、降级、熔断   ---->   顺序该如何保证   责任链方式：FlowSlot   DegradeSlot
     */
    @RequestMapping("/test")
    public String test(){
        return "user-service test";
    }


/*    @RequestMapping("/login")
    @SentinelResource("login")
    public String login(@RequestParam(required = false) String username,
                        @RequestParam(required = false) String password){

        return username+":"+ password;
    }*/

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/call")
    public String call(){
        // java.net.HttpURLConnection   HttpClient   OkHttp   RestTemplate   Feign    Socket
        // http://localhost:9091/order/query 可能是多变的
        return restTemplate.getForObject("http://localhost:9091/order/query",String.class);
    }

    @Resource
    private DiscoveryClient discoveryClient;

    // 表示服务发现
    @RequestMapping("/getinstances")
    public List<ServiceInstance> getinstances(){
        return discoveryClient.getInstances("order-service");
    }

    // 实现负载均衡
    @RequestMapping("/test1")
    public String test1(){
        // discoveryClient.getInstances("order-service");--->urls--->url
        // restTemplate进行调用
        //  "uri": "http://192.168.1.3:9092,9091",
        List<ServiceInstance> instances = discoveryClient.getInstances("order-service");
        List<String> uris = instances.stream().
                map(instance -> instance.getUri().toString() + "/order/query").collect(Collectors.toList());
        // 使用随机的负载均衡算法得到一个uri
        int index= ThreadLocalRandom.current().nextInt(uris.size());
        String url=uris.get(index);
        return restTemplate.getForObject(url,String.class);
    }

    @Resource
    private LoadBalancerClient loadBalancerClient;   // 从Spring IoC容器中获取该类的实现类

    // 使用Ribbon实现负载均衡
    // 实现负载均衡
    // Ribbon: 服务发现+负载均衡
    @RequestMapping("/test2")
    public String test2(){
        // Ribbon的API使用方式   默认使用的轮询的负载均衡算法
        ServiceInstance serviceInstance = loadBalancerClient.choose("order-service");
        String url = serviceInstance.getUri().toString() + "/order/query";
        return restTemplate.getForObject(url,String.class);
    }

    // Ribbon的其他使用方式+RestTemplate：强耦合的
    @Resource
    private RestTemplate ribbonRestTemplate;
    @RequestMapping("/test3")
    public String test3(){
        return this.ribbonRestTemplate.getForObject("http://order-service/order/query",String.class);
    }

    // 思考：http://order-service/order/query   更加倾向于：Object#method

    // 使用OpenFeign进行远程调用
    @Resource
    private OrderServiceFeignClient orderServiceFeignClient;
    @RequestMapping("/testopenfeign")
    public String testopenfeign(@RequestParam String param){
        // TODO: 该方法不是没有实现吗？   --->类比MyBatis    UserMapper直接使用？    配置了sql语句，底层帮你生成了动态代理实现类
        return orderServiceFeignClient.query(param);
    }

/*    // 使用nacos作为配置中心中的属性
    @Value("${person.username}")
    private String personUsername;

    @RequestMapping("/nacosconfig")
    public String nacosconfig(){
        return this.personUsername;
    }*/

/*    @Resource
    private RocketMQTemplate rocketMQTemplate;
    // 生产消息
    @RequestMapping("/produce")
    public void produce(){
        this.rocketMQTemplate.convertAndSend("jack-topic","hello Jack.");
    }*/
}








